<template>
    <div class="a-carousel" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
        <div class="a-carousel__container" :style="{ height: props.height }">
            <button class="a-carousel__arrow a-carousel__arrow--left flex-y flex-x" :class="{'a-carousel__arrow--always':props.arrow == 'always'}" @click="handleMoveLeft" v-if="props.arrow !== 'never'">
                <el-icon color="#fff">
                    <ArrowLeft />
                </el-icon>
            </button>
            <button class="a-carousel__arrow a-carousel__arrow--right flex-y flex-x" :class="{ 'a-carousel__arrow--always': props.arrow == 'always' }" @click="handleMoveRight"  v-if="props.arrow !== 'never'">
                <el-icon color="#fff">
                    <ArrowRight />
                </el-icon>
            </button>
            <div ref="scrollRef" class="a-carousel__scroll" w-full h-full
                :style="{ transform: translateStyle.transfrom, transition: translateStyle.transition }">
                <slot></slot>
            </div>
        </div>

        <ul class="a-carousel__indicators"
            :class="{ 'a-carousel__indicators--outside': props.indicatorPosition == 'outside' }">
            <li class="a-carousel__indicators--item" v-for="(item, index) in count"
                @mouseenter="trigger == 'hover' ? handleClickIndicator(index) : () => { }"
                @click="trigger == 'click' ? handleClickIndicator(index) : () => { }">
                <div class="a-carousel__button"
                    :class="{ 'a-carousel__button--active': index == currentIndex, 'a-carousel__outside--btn': props.indicatorPosition == 'outside' }">
                </div>
            </li>
        </ul>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'

interface Props {
    height?: string,
    initialIndex?: number,
    trigger?: 'hover' | 'click',
    autoplay?: boolean,
    interval?: number,
    indicatorPosition?: 'outside' | 'none',
    arrow?:'always'|'hover'|'never',
    pauseOnHover?:boolean
}

const props = withDefaults(defineProps<Props>(), {
    initialIndex: 0,
    trigger: 'click',
    autoplay: false,
    interval: 3000,
    indicatorPosition: 'none',
    arrow:'hover',
    pauseOnHover:true
})

const count = ref(0)
const scrollRef = ref<HTMLDivElement>()
let clear: any = null

onMounted(() => {
    count.value = scrollRef.value?.children.length as number
    //复制第一张图加到轮播图父元素，复制最后一张图插入到子元素第一位，用于实现无缝切换
    const first = scrollRef.value?.firstElementChild?.cloneNode(true) as Node
    const end = scrollRef.value?.lastElementChild?.cloneNode(true) as Node
    scrollRef.value?.appendChild(first)
    scrollRef.value?.insertBefore(end, scrollRef.value?.firstElementChild as Node)
    if (props.initialIndex != 0) {
        currentIndex.value = props.initialIndex
        translateStyle.transfrom = `translateX(-${(currentIndex.value + 1) * 100}%)`
    } else {
        translateStyle.transfrom = 'translateX(-100%)'
    }
    if (props.autoplay) {
        clear = setInterval(() => {
            handleMoveRight()
        }, props.interval)
    }
})

onUnmounted(() => {
    clearInterval(clear)
})

//鼠标悬停暂停自动切换
const handleMouseEnter = () => {
    if(props.autoplay && props.pauseOnHover){
        clearInterval(clear)
    }
}

//鼠标离开，继续播放
const handleMouseLeave = () => {
    if (props.autoplay && props.pauseOnHover) {
        clear = setInterval(() => {
            handleMoveRight()
        }, props.interval)
    }
}

const translateStyle = reactive({
    transfrom: '0px',
    transition: 'none'
})

const currentIndex = ref(0)
const moveTo = () => {
    //异步一下，不然translateStyle.transition = 'none'不生效
    setTimeout(() => {
        translateStyle.transfrom = `translateX(-${(currentIndex.value + 1) * 100}%)`
        translateStyle.transition = 'all .3s ease-in'
    }, 50)
}

const handleMoveLeft = () => {
    if (currentIndex.value == 0) {
        currentIndex.value = count.value
        translateStyle.transition = 'none'
        translateStyle.transfrom = `translateX(-${(currentIndex.value + 1) * 100}%)`
    }
    currentIndex.value--
    moveTo()
}

const handleMoveRight = () => {
    if (currentIndex.value == count.value - 1) {
        currentIndex.value = -1
        translateStyle.transition = 'none'
        scrollRef.value?.offsetHeight
        translateStyle.transfrom = `translateX(-${(currentIndex.value + 1) * 100}%)`
    }
    currentIndex.value++
    moveTo()
}

const handleClickIndicator = (index: number) => {
    currentIndex.value = index
    moveTo()
}

defineExpose({
    currentIndex
})
</script>

<style scoped lang="scss">
.a-carousel {
    position: relative;
    text-align: center;

    &__container {
        overflow: hidden;
        position: relative;
    }

    &__scroll {
        display: flex;

    }

    &__arrow {
        height: 36px;
        width: 36px;
        border-radius: 50%;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        z-index: 1;
        background-color: rgba(31, 45, 61, .11);
        border: none;
        display: none;
        outline: 0;

        &--left {
            left: 0px;
        }

        &--right {
            right: 0px;
        }

        &:hover {
            background-color: rgba(31, 45, 61, .23);

        }
    }

    &:hover &__arrow {
        display: flex;
    }

    &__arrow--always{
        display: flex;
    }

    &__indicators {
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
        list-style: none;
        display: inline-flex;
        margin: 0;
        padding: 0;

        &--item {
            display: inline-block;
            padding: 6px 4px;
            cursor: pointer;
        }

        &--outside {
            position: static;
            transform: translateX(0);
        }
    }


    &__button {
        height: 8px;
        width: 8px;
        border-radius: 50%;
        background-color: var(--n-dot-color);
        transition: all .2s;
    }

    &__outside--btn {
        background-color: #c0c4cc;
        opacity: .24;
    }
}

.a-carousel .a-carousel__button--active {
     background-color: var(--n-dot-color-active);
     transform: scale(1.4);
}</style>